package com.bigdata

object Demo13Fun {

  def main(args: Array[String]): Unit = {


    /**
     * 2、以函数作为返回值
     * (String) => Int
     */
    def fun(x: String): String => Int = {

      def f1(y: String): Int = {
        // 内层函数中是可以使用外层函数中的参数值 (闭包)
        x.toInt + y.toInt
      }

      f1
    }

    val result1: String => Int = fun("100")

    val result2: Int = result1("200")
    println(result2)

    // 柯里化
    val result3: Int = fun("20")("30")
    println(result3)


    /**
     * 简写上面的函数   -- 函数柯里化
     * 函数的返回值是函数，并且返回的函数参数是第二个括号的入参
     */
    def fun2(str: String)(s: String): Int = {
      str.toInt + s.toInt
    }

    val result4: Int = fun2("100")("200")
    println(result4)

    val fun3: String => Int = fun2("100")

    println(fun3("10"))
    println(fun3("20"))

    def fun4(str: String, s: String) = {
      str.toInt + s.toInt
    }

    val result5 = fun4("20", "30")
    println(result5)

    // 可变参数只能放在函数中的最后一个参数上
    def fun5(str: String, num: Int*): Unit = {
      println(str)
      println(num.toList)
      println("fun5")
    }

    fun5("aaa", 1, 2, 3)

    println("*" * 100)

    /**
     * 想要把可变参数放在非最后一个参数的位置，可以使用柯里化来实现
     * @param num
     * @param str
     */
    def fun6(num: Int*)(str: String): Unit = {
      println(str)
      println(num.toList)
      println("fun6")
    }

    fun6(4, 5, 6, 7)("bbb")

    // 偏函数，先传递部分参数，得到一个函数，再次调用这个函数的时候只需要传递额外的参数即可
    val fun7: String => Int = fun4("100", _)
    println(fun7("10"))
    println(fun7("20"))


    // 函数的参数和返回值都是函数
    def fun8(f1: String => Int): String => Int = {
      println("fun8...")
      f1
    }

    // 把fun8赋值给一个变量
    val fun9: (String => Int) => (String => Int) = fun8

    val fun10: String => Int = fun8((x: String) => {
      x.toInt * 2
    })

    val result: Int = fun10("20")
    println(result)


  }

}
